import { computed } from 'vue'
import { isJSON } from 'class-validator'

/**
 * 使用socket
 *
 * @param {Ref} wsUrl 链接地址
 * @param {(data) => void} msgHandler 消息处理
 * @returns
 */
export const useSocket = (wsUrl, msgHandler) => {
  let socket = null
  let lockReconnect = false // 避免重复连接

  let heartTimeId = 0
  let reTimeId = 0

  const RE_COUNT = 3
  // 重连次数
  let connetnum = RE_COUNT
  // 当前链接地址
  const currentUrl = computed(() => wsUrl.value)
  // 创建链接
  const initSocket = () => {
    try {
      if (!currentUrl.value) {
        throw new Error('请输入正确的链接地址')
      }
      socket = new WebSocket(currentUrl.value)
      socktHandler()
    } catch (e) {
      reconnect()
    }
  }

  // 重连
  const reconnect = () => {
    if (connetnum <= 0 || lockReconnect) {
      return
    }
    console.log('开始重连')
    // 避免多次重复链接
    lockReconnect = true
    // 关闭当前心跳
    if (heartTimeId) {
      clearInterval(heartTimeId)
      heartTimeId = 0
    }
    reTimeId = setInterval(() => {
      console.log(`第 ${RE_COUNT - connetnum + 1} 次重连`)
      initSocket()
      connetnum = connetnum - 1
      // 防止多次重复链接过来
      if (connetnum <= 0) {
        lockReconnect = false
        // 次数用完后不再重连，清除掉insterval
        if (reTimeId) {
          clearInterval(reTimeId)
          reTimeId = 0
        }
      }
    }, 5000)
  }

  // socket 处理
  const socktHandler = () => {
    // 链接打开
    socket.onopen = () => {
      console.log('链接已打开')
      if (!heartTimeId) {
        heartTimeId = setInterval(() => {
          console.log('心跳发送')
          socket.send('SocketHeart')
        }, 10 * 1000)
      }
      // 重置重连次数 将重连的定时器关闭
      connetnum = RE_COUNT
      lockReconnect = false
      if (reTimeId) {
        clearInterval(reTimeId)
        reTimeId = 0
      }
    }
    // 处理消息
    socket.onmessage = (res) => {
      if (!isJSON(res.data)) {
        return
      }
      msgHandler(JSON.parse(res.data))
    }
    // 链接出错
    socket.onerror = (err) => {
      console.log('链接出错 >>>', err)
      reconnect()
    }
    // 关闭链接
    socket.onclose = (evt) => {
      console.log(`链接关闭 code >> ${evt.code}`)
      if (evt.code === 1000) {
        socket = null
      } else if (evt.code === 1001 || evt.code === 1006) {
        reconnect()
      } else {
        console.log('未知原因导致链接关闭')
      }
    }
  }

  // 发送消息
  const sendSocketMsg = (data) => {
    if (socket) {
      try {
        socket.send(JSON.stringify(data))
      } catch (error) {
        console.log(`发送消息失败error >>`, error)
      }
    } else {
      console.log('未链接socket')
    }
  }

  // 关闭链接
  const colseSocket = () => {
    if (socket) {
      socket.close()
    }
    if (heartTimeId) {
      clearInterval(heartTimeId)
      heartTimeId = 0
    }
  }

  return {
    colseSocket,
    sendSocketMsg,
    initSocket
  }
}
